//! 撮合引擎
use anyhow::Result;
use dashmap::DashMap;
use eztrade_dto::{
    order::{Direction, Order, OrderStatus, PositionEffect},
    tick::{Orderstack, TickData},
};
use rayon::prelude::*;
use serde::Serialize;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::{
    collections::{BTreeMap, VecDeque},
    sync::RwLock,
};

/// 订单簿结构
///
/// 订单簿结构应该是价格优先/时间优先的,
/// 使用 BTreeMap 来存储价格, VecDeque 来存储时间先后的订单
pub struct OrderBook {
    // 买盘 (价格降序)
    pub bids: BTreeMap<u64, VecDeque<Arc<RwLock<Order>>>>, // price_in_cents -> orders
    // 卖盘 (价格升序)
    pub asks: BTreeMap<u64, VecDeque<Arc<RwLock<Order>>>>, // price_in_cents -> orders
}

/// 成交记录结构
#[derive(Debug, Clone, Serialize)]
pub struct Trade {
    pub trade_id: u64,
    pub symbol: String,
    pub price_cent: u64, // 成交价格(单位: 分)
    pub quantity: u64,
    // 买卖方order_id
    pub id_long: u64,
    pub id_short: u64,
    pub fee_long_cent: u64,  // 买方手续费
    pub fee_short_cent: u64, // 卖方手续费
    pub timestamp_us: u64,
}

pub trait MatchEngineTrait {
    // 撮合接口抽象（供清算与交易所驱动）
    fn place_order(&self, order: Arc<RwLock<Order>>) -> Result<Order>;
    fn cancel_order(&self, order_id: u64) -> Result<()>;
    // 将无效订单去除
    fn update_orderbooks(&self);
    fn place_order_queue_into_book(&self);
    fn match_all_symbols(&self);
    // 获取交易记录
    fn trades(&self) -> &DashMap<String, VecDeque<Trade>>;
    // 获取完结订单
    fn done_orders(&self) -> &DashMap<u64, Arc<RwLock<Order>>>;
    // 获取最新价格情况
    fn get_last_price_cent(&self) -> &DashMap<String, u64>;
    // 获取最新订单簿
    fn get_last_order_book(&self, symbol: &str) -> Option<TickData>;
}

pub struct MatchEngine {
    pub current_timestamp_us: AtomicU64,
    // 交易ID生成器
    pub trade_id_generator: AtomicU64,
    // 分离的买卖盘
    pub order_books: DashMap<String, OrderBook>,
    // 最新成交数据
    pub last_price_cent: DashMap<String, u64>,
    // 实时tick数据
    pub tick_data: DashMap<String, TickData>,
    // 订单队列
    pub order_queue: DashMap<String, VecDeque<Arc<RwLock<Order>>>>, // symbol -> VecDeque<Order>
    // 活跃订单索引
    pub active_orders: DashMap<u64, Arc<RwLock<Order>>>, // order_id -> order
    // 完结订单索引
    pub done_orders: DashMap<u64, Arc<RwLock<Order>>>, // order_id -> order
    // 临时成交缓冲
    pub trades: DashMap<String, VecDeque<Trade>>,
}

impl MatchEngineTrait for MatchEngine {
    fn trades(&self) -> &DashMap<String, VecDeque<Trade>> {
        &self.trades
    }

    fn done_orders(&self) -> &DashMap<u64, Arc<RwLock<Order>>> {
        &self.done_orders
    }

    /// 挂单 - 将订单放入订单簿队列(避免持有订单簿锁)
    fn place_order(&self, arc_order: Arc<RwLock<Order>>) -> Result<Order> {
        let order_cloned = {
            let order_inside = arc_order.read().unwrap();
            order_inside.clone()
        };
        let order_id = order_cloned.id.unwrap();
        let symbol = order_cloned.symbol.clone();
        {
            let mut order_queue = self
                .order_queue
                .entry(symbol.clone())
                .or_insert_with(VecDeque::new);
            // 添加到活跃订单索引
            self.active_orders.insert(order_id, arc_order.clone());
            order_queue.push_back(arc_order);
        }
        Ok(order_cloned)
    }

    /// 撤单
    fn cancel_order(&self, order_id: u64) -> Result<()> {
        // 从活跃订单索引中查找订单
        let order_ref_res = self.active_orders.get(&order_id).ok_or_else(|| {
            log::warn!("订单 {} 未在活跃订单中", order_id);
            anyhow::anyhow!("订单未在活跃订单中")
        });
        let order_ref = match order_ref_res {
            Ok(order) => order,
            Err(e) => return Err(e),
        };
        // 获取写锁并更新订单状态
        {
            let mut order = order_ref.write().unwrap();
            if matches!(
                order.status,
                OrderStatus::Filled | OrderStatus::Canceled | OrderStatus::Rejected
            ) {
                return Err(anyhow::anyhow!("订单已完成或被取消，无法撤销"));
            }
            order.status = OrderStatus::Canceled;
        }
        self.done_orders.insert(order_id, order_ref.clone());
        Ok(())
    }

    /// 挂单队列放入订单簿内
    fn place_order_queue_into_book(&self) {
        for mut entry in self.order_queue.iter_mut() {
            let symbol = entry.key().clone();
            let order_queue = entry.value_mut();
            let mut order_book = self
                .order_books
                .entry(symbol.clone())
                .or_insert_with(|| OrderBook::new());

            while let Some(arc_order) = order_queue.pop_front() {
                let order = arc_order.read().unwrap();
                if order.status == OrderStatus::Canceled {
                    // 如果订单已取消，跳过
                    self.done_orders
                        .insert(order.id.unwrap(), arc_order.clone());
                    continue;
                }
                let price_cents = (order.price.unwrap() * 100.0) as u64; // 转换为分为单位
                match (order.direction, order.position_effect) {
                    (Direction::Long, PositionEffect::Open)
                    | (Direction::Short, PositionEffect::Close) => {
                        order_book
                            .bids
                            .entry(price_cents)
                            .or_insert_with(VecDeque::new)
                            .push_back(arc_order.clone());
                    }
                    (Direction::Short, PositionEffect::Open)
                    | (Direction::Long, PositionEffect::Close) => {
                        order_book
                            .asks
                            .entry(price_cents)
                            .or_insert_with(VecDeque::new)
                            .push_back(arc_order.clone());
                    }
                }
            }
        }
    }

    /// 对所有品种进行撮合
    fn match_all_symbols(&self) {
        self.order_books
            .par_iter_mut()
            .for_each(|mut order_book_ref| {
                let symbol = order_book_ref.key().clone();
                self.match_symbol(&symbol, &mut order_book_ref);
            });
    }

    /// 更新有效订单簿(去除不必要订单)
    fn update_orderbooks(&self) {
        self.order_books.par_iter_mut().for_each(|mut entry| {
            let orderbook = entry.value_mut();
            orderbook.asks.par_iter_mut().for_each(|(_price, orders)| {
                orders.retain(|o| {
                    let order = o.read().unwrap();
                    !matches!(
                        order.status,
                        OrderStatus::Canceled | OrderStatus::Rejected | OrderStatus::Filled
                    )
                });
            });
            orderbook.bids.par_iter_mut().for_each(|(_price, orders)| {
                orders.retain(|o| {
                    let order = o.read().unwrap();
                    !matches!(
                        order.status,
                        OrderStatus::Canceled | OrderStatus::Rejected | OrderStatus::Filled
                    )
                });
            });
        });
    }

    /// 获取最新价格情况
    fn get_last_price_cent(&self) -> &DashMap<String, u64> {
        &self.last_price_cent
    }

    fn get_last_order_book(&self, symbol: &str) -> Option<TickData> {
        self.tick_data.get(symbol).map(|f| f.clone())
    }
}

impl MatchEngine {
    pub fn new() -> Self {
        Self {
            current_timestamp_us: AtomicU64::new(0),
            trade_id_generator: AtomicU64::new(1),
            order_books: DashMap::new(),
            order_queue: DashMap::new(),
            last_price_cent: DashMap::new(),
            tick_data: DashMap::new(),
            trades: DashMap::new(),
            active_orders: DashMap::new(),
            done_orders: DashMap::new(),
        }
    }

    /// 更新当前时间戳(外部传入timestamp)
    pub fn update_timestamp(&self, timestamp_us: u64) {
        self.current_timestamp_us
            .store(timestamp_us, Ordering::Release);
    }

    /// 订单撮合逻辑
    fn create_trade_orders(
        &self,
        long_order: &mut Order,
        short_order: &mut Order,
        match_price_cent: u64,
        timestamp_us: u64,
    ) -> (Option<Order>, Option<Order>) {
        // 如果是继承订单，不应该调用此方法
        if long_order.inherited || short_order.inherited {
            panic!("unreachable");
        }

        if !matches!(
            long_order.status,
            OrderStatus::Unfilled | OrderStatus::PartiallyFilled
        ) || !matches!(
            short_order.status,
            OrderStatus::Unfilled | OrderStatus::PartiallyFilled
        ) {
            // 订单状态不正确，无法撮合
            return (None, None);
        }

        let deal_price = match_price_cent as f64 / 100.0;

        // 根据数量大小关系
        match long_order.quantity.cmp(&short_order.quantity) {
            std::cmp::Ordering::Equal => {
                // 两个订单数量相等，都完全成交
                long_order.status = OrderStatus::Filled;
                long_order.timestamp_us = Some(timestamp_us);
                short_order.status = OrderStatus::Filled;
                short_order.timestamp_us = Some(timestamp_us);
                (Some(long_order.clone()), Some(short_order.clone()))
            }
            std::cmp::Ordering::Less => {
                if short_order.next_id > 99 {
                    short_order.status = OrderStatus::Rejected;
                    (Some(long_order.clone()), None)
                } else {
                    // 买单数量小，买单完全成交，卖单部分成交
                    long_order.status = OrderStatus::Filled;
                    long_order.timestamp_us = Some(timestamp_us);
                    long_order.price = Some(deal_price);

                    // 卖单部分成交：创建子订单
                    let mut short_child = short_order.clone();
                    short_order.next_id += 1;
                    short_child.price = Some(deal_price);
                    short_child.quantity = long_order.quantity;
                    short_order.quantity -= long_order.quantity;
                    short_child.id =
                        Some(short_child.id.expect("父订单ID缺失") + short_order.next_id as u64);
                    short_child.status = OrderStatus::Filled;
                    short_child.inherited = true;
                    short_child.timestamp_us = Some(timestamp_us);
                    // 更新父订单状态为部分成交
                    short_order.status = OrderStatus::PartiallyFilled;
                    (Some(long_order.clone()), Some(short_child))
                }
            }
            std::cmp::Ordering::Greater => {
                if long_order.next_id > 99 {
                    long_order.status = OrderStatus::Rejected;
                    (None, Some(short_order.clone()))
                } else {
                    // 买单数量大，卖单完全成交，买单部分成交
                    short_order.status = OrderStatus::Filled;
                    short_order.timestamp_us = Some(timestamp_us);
                    short_order.price = Some(deal_price);

                    // 买单部分成交：创建子订单
                    let mut long_child = long_order.clone();
                    long_order.next_id += 1;
                    long_child.quantity = short_order.quantity;
                    long_order.quantity -= short_order.quantity;
                    long_child.id =
                        Some(long_child.id.expect("父订单ID缺失") + long_order.next_id as u64);
                    long_child.price = Some(deal_price);
                    long_child.status = OrderStatus::Filled;
                    long_child.inherited = true;
                    long_child.timestamp_us = Some(timestamp_us);

                    // 更新父订单状态为部分成交
                    long_order.status = OrderStatus::PartiallyFilled;
                    (Some(long_child), Some(short_order.clone()))
                }
            }
        }
    }

    /// 对单个品种进行撮合
    fn match_symbol(&self, symbol: &str, order_book: &mut OrderBook) {
        let mut new_trades = Vec::new();
        log::trace!(
            "bids len:{}, asks len:{}",
            order_book.bids.iter().len(),
            order_book.asks.iter().len()
        );
        // 价格优先(最高买价对接最低卖价)/时间优先撮合
        while let (Some((&highest_bid_price, _)), Some((&lowest_ask_price, _))) = (
            order_book.bids.iter().rev().next(),
            order_book.asks.iter().next(),
        ) {
            log::trace!(
                "当前撮合价位: 买价 {}, 卖价 {}",
                highest_bid_price,
                lowest_ask_price
            );
            // 成交价格
            let mut deal_price_cent = lowest_ask_price;

            // 判断是否都是市价单的特殊情况
            let is_buy_market = highest_bid_price >= (i64::MAX as u64 / 100);
            let is_sell_market = lowest_ask_price == 0;
            if is_sell_market {
                // 卖单为市价单时，撮合价需要进行调整
                deal_price_cent = highest_bid_price;
            }

            if is_buy_market && is_sell_market {
                // 两个都是市价单时，撮合价需要进行调整
                let last_price = self.last_price_cent.get(symbol).map(|r| *r).unwrap_or(0);
                let next_bid = order_book
                    .bids
                    .iter()
                    .rev()
                    .nth(1)
                    .map(|(&price, _)| price)
                    .unwrap_or(last_price);
                let next_ask = order_book
                    .asks
                    .iter()
                    .nth(1)
                    .map(|(&price, _)| price)
                    .unwrap_or(last_price);
                deal_price_cent = std::cmp::min(next_bid, next_ask);
            }

            if deal_price_cent == 0 {
                // 经过调整还为0则说明订单簿无记录且无可成交的订单, 直接break
                log::warn!("撮合失败: 买单或卖单状态不正确");
                break;
            }

            if highest_bid_price >= deal_price_cent {
                // 可以成交
                let bid_orders = order_book.bids.get_mut(&highest_bid_price).unwrap();
                let ask_orders = order_book.asks.get_mut(&lowest_ask_price).unwrap();

                // 清理空的价位
                if bid_orders.is_empty() {
                    order_book.bids.remove(&highest_bid_price);
                    continue;
                }
                if ask_orders.is_empty() {
                    order_book.asks.remove(&lowest_ask_price);
                    continue;
                }
                log::trace!(
                    "当前撮合价 asks长度: {}, bids长度: {}",
                    ask_orders.len(),
                    bid_orders.len()
                );

                // 推出最前面的订单进行撮合
                if let (Some(arc_buy_order), Some(arc_sell_order)) =
                    (bid_orders.pop_front(), ask_orders.pop_front())
                {
                    let arc_buy_order_matching = arc_buy_order.clone();
                    let arc_sell_order_matching = arc_sell_order.clone();
                    let mut buy_order = arc_buy_order_matching.write().unwrap();
                    let mut sell_order = arc_sell_order_matching.write().unwrap();
                    log::trace!(
                        "撮合订单: 买单ID {}, 卖单ID {}",
                        buy_order.id.unwrap(),
                        sell_order.id.unwrap()
                    );
                    let timestamp_us = self.current_timestamp_us.load(Ordering::Acquire);
                    // 使用下单撮合逻辑创建成交订单
                    let (buy_trade_order, sell_trade_order) = self.create_trade_orders(
                        &mut buy_order,
                        &mut sell_order,
                        deal_price_cent,
                        timestamp_us,
                    );

                    // 如果两个订单都成功创建成交记录(价格撮合成功后需要进入Clearing计算手续费和仓位变动)
                    match (buy_trade_order, sell_trade_order) {
                        // 生成成交记录
                        (Some(buy_filled), Some(sell_filled)) => {
                            log::trace!(
                                "撮合成功, 此时长度: 买单 {}, 卖单 {}",
                                bid_orders.len(),
                                ask_orders.len()
                            );
                            let trade = Trade {
                                trade_id: self.trade_id_generator.fetch_add(1, Ordering::SeqCst),
                                symbol: symbol.to_string(),
                                price_cent: deal_price_cent,
                                quantity: sell_filled.quantity,
                                id_long: buy_filled.id.unwrap(),
                                id_short: sell_filled.id.unwrap(),
                                fee_long_cent: 0, // 买方手续费 暂时为0, 结算中心处赋值
                                fee_short_cent: 0, // 卖方手续费 暂时为0, 结算中心处赋值
                                timestamp_us,
                            };

                            new_trades.push(trade);

                            // 将成交的子订单放入完结订单
                            self.done_orders
                                .insert(buy_filled.id.unwrap(), Arc::new(RwLock::new(buy_filled)));
                            self.done_orders.insert(
                                sell_filled.id.unwrap(),
                                Arc::new(RwLock::new(sell_filled)),
                            );
                        }
                        (None, None) => {
                            log::trace!("撮合失败: 买单或卖单状态不正确");
                        }
                        _ => {}
                    };

                    // 如果订单状态为完成/拒接或者取消，直接移除活跃, 并放入完结订单
                    if matches!(
                        buy_order.status,
                        OrderStatus::Filled | OrderStatus::Rejected | OrderStatus::Canceled
                    ) {
                        self.active_orders.remove(&buy_order.id.unwrap());
                        self.done_orders.insert(
                            buy_order.id.unwrap(),
                            Arc::new(RwLock::new(buy_order.clone())),
                        );
                    }
                    if matches!(
                        sell_order.status,
                        OrderStatus::Filled | OrderStatus::Rejected | OrderStatus::Canceled
                    ) {
                        self.active_orders.remove(&sell_order.id.unwrap());
                        self.done_orders.insert(
                            sell_order.id.unwrap(),
                            Arc::new(RwLock::new(sell_order.clone())),
                        );
                    }

                    // 如果订单未成交且还有剩余，重新放回队列
                    if matches!(
                        buy_order.status,
                        OrderStatus::Unfilled | OrderStatus::PartiallyFilled
                    ) && buy_order.quantity > 0
                    {
                        bid_orders.push_front(arc_buy_order);
                    }
                    if matches!(
                        sell_order.status,
                        OrderStatus::Unfilled | OrderStatus::PartiallyFilled
                    ) && sell_order.quantity > 0
                    {
                        ask_orders.push_front(arc_sell_order);
                    }
                }
            } else {
                log::trace!(
                    "当前撮合价位不交叉: 买价 {}, 卖价 {}",
                    highest_bid_price,
                    lowest_ask_price
                );
                break; // 价格不交叉时无法继续撮合
            }
        }

        // 保存成交记录
        if !new_trades.is_empty() {
            let mut trades = self
                .trades
                .entry(symbol.to_string())
                .or_insert_with(VecDeque::new);
            for trade in new_trades {
                log::trace!("trade {:?}", trade);
                trades.push_back(trade);
            }
        }
        // 更新市场数据
        self.update_market_data(symbol, order_book);
    }

    /// 更新市场数据
    fn update_market_data(&self, symbol: &str, order_book: &OrderBook) {
        let mut asks = Vec::new();
        let mut bids = Vec::new();

        // 仅构建5档数据
        // 构建卖盘数据 (价格正序)
        for (&price_cents, orders) in order_book.asks.iter().take(5) {
            if price_cents == 0 {
                continue;
            }
            let total_volume = orders
                .par_iter()
                .map(|o| {
                    let order = o.read().unwrap();
                    match order.status {
                        OrderStatus::Unfilled | OrderStatus::PartiallyFilled => order.quantity,
                        _ => 0,
                    }
                })
                .sum::<u64>() as u32;
            asks.push(Orderstack {
                price: price_cents as f32 / 100.0,
                volume: total_volume,
            });
        }

        // 构建买盘数据 (价格倒序)
        for (&price_cents, orders) in order_book.bids.iter().rev().take(5) {
            if price_cents >= (0x8000000000000000) {
                // 闪电单, 不进入orderbook
                continue;
            }
            let total_volume = orders
                .par_iter()
                .map(|o| {
                    let order = o.read().unwrap();
                    match order.status {
                        OrderStatus::Unfilled | OrderStatus::PartiallyFilled => order.quantity,
                        _ => 0,
                    }
                })
                .sum::<u64>() as u32;
            bids.push(Orderstack {
                price: price_cents as f32 / 100.0,
                volume: total_volume,
            });
        }

        // 更新最后价格的顺序为 最后成交价>手动记录的最后价>卖一价>买一价>1.0
        let first_ask_price = asks.first().map(|o| o.price).unwrap_or_else(|| {
            let first_bid_price = bids.first().map(|o| o.price).unwrap_or_else(|| {
                log::trace!("No bid price found for {}, using 1.0", symbol);
                1.0
            });
            log::trace!("No ask price found for {}, using first_bid_price", symbol);
            first_bid_price
        });

        // 更新 lastprice (最后成交, 无交易则获取记录的价格)
        let last_price = match self
            .trades
            .get(symbol)
            .and_then(|trades| trades.back().map(|trade| trade.price_cent))
        {
            Some(last_price_cent) => {
                self.last_price_cent
                    .insert(symbol.to_string(), last_price_cent);
                last_price_cent as f32 / 100.0
            }
            None => self
                .last_price_cent
                .get(symbol)
                .map(|r| *r as f32 / 100.0)
                .unwrap_or_else(|| {
                    log::warn!("No last price found for {}, using first ask price", symbol);
                    self.last_price_cent
                        .insert(symbol.to_string(), (first_ask_price * 100.0) as u64);
                    first_ask_price
                }),
        };

        // 更新 TickData / Orderbook
        let tick_data = TickData::new(
            self.current_timestamp_us.load(Ordering::Acquire),
            symbol.to_string(),
            last_price,
            asks,
            bids,
        );

        self.tick_data.insert(symbol.to_string(), tick_data);
    }
}

impl OrderBook {
    pub fn new() -> Self {
        Self {
            bids: BTreeMap::new(),
            asks: BTreeMap::new(),
        }
    }
}
